package com.mrx.java8.stream;

import com.mrx.java8.lambda.Employee;
import org.junit.jupiter.api.Test;

import java.util.*;
import java.util.stream.Stream;

/**
 * “集合讲的是数据，流讲的是计算”
 * 一、Stream 的三个步骤
 * 1、创建Stream
 * 2、中间操作
 * 3、终止操作
 */
public class StreamApi2 {

    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9999.99),
            new Employee("李四",38,5555.55),
            new Employee("王五",50,6666.66),
            new Employee("赵六",16,3333.33),
            new Employee("田七",8,7777.77)
    );

    // 中间操作
    /**
     * 筛选与切片
     * filter--接收Lambda,从流中排除某些元素
     * limit--截断流，使其元素不超过给定的数量
     * skip(n) -- 跳过元素，返回一个扔掉了前n个元素的流。若流中元素不足n个，则返回一个空流，与limit(n)互补
     * distinct-- 筛选，通过流所产生元素的hashcode()和equals()去除重复元素
     */

    // 内部迭代:迭代操作由Stream API完成
    @Test
    public void test1(){
        // 中间操作:不会执行任何操作
        /**
         * 多个中间操作可以连接起来形成一个流水线，除非流水线上触发终止操作，
         * 否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理，称为"惰性求值"
         */
        Stream<Employee> stream1 =  employees.stream()
                .filter(employee -> {
                    System.out.println("Stream API 的中间操作");
                    return employee.getAge() > 35;
                });

        // 终止操作:一次性执行全部内容，即"惰性求值"
        stream1.forEach(System.out::println);
    }


    // 外部迭代
    @Test
    public void test2(){
        Iterator<Employee> iterator = employees.iterator();
        while (iterator.hasNext()){
            Employee employee = iterator.next();
            System.out.println(employee);
        }
    }


    // limit
    @Test
    public void test3(){
        employees.stream()
                .filter((e)->{
                    System.out.println("短路"); //&& ||
                    return e.getSalary()>5000;
                })
                .limit(2) // 一段发现两条，前面就不再过滤。可以提高效率
                .forEach(System.out::println);
    }

    // skip
    @Test
    public void test4(){
        employees.stream()
                .filter(e->e.getSalary()>5000)
                .skip(2)
                .forEach(System.out::println);
    }

    // distinct 去重 需要产生hashcode()和equals()
    @Test
    public void test5(){
        List<Employee> myList = new ArrayList<>(employees);
        myList.add(new Employee("田七",8,7777.77));
        myList.add(new Employee("田七",8,7777.77));
        myList.add(new Employee("田七",8,7777.77));

        myList.stream().forEach(System.out::println);
        System.out.println("------------------------------");
        myList.stream()
                .distinct()
                .forEach(System.out::println);
    }

    /**
     * 映射
     * map--接收lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数，
     *      该函数会被应用到每个元素上，并将其映射成一个新元素。
     * flatMap--接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流
     *
     * List中 add(Object object)
     *        addAll(Collection collection)
     *
     *
     */
    @Test
    public void test6(){  //
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
        list.stream()
                .map(s -> s.toUpperCase())
                .forEach(System.out::println);

        System.out.println("-----------------------------------------------");
        employees.stream()
                .map(e->e.getName())
                .forEach(System.out::println);


        System.out.println("-----------------------------------------------");
        Stream<Stream<Character>> stream = list.stream()
                .map(StreamApi2::filterCharacter);
        stream.forEach(sm->{
            sm.forEach(System.out::println);
        });
        System.out.println("-----------------------------------------------");
        Stream<Character> stream1 =  list.stream()
                .flatMap(StreamApi2::filterCharacter);
        stream1.forEach(System.out::println);
    }

    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for(Character ch : str.toCharArray()){
            list.add(ch);
        }
        return list.stream();
    }

    /**
     *   List中 add(Object object)              map
     *          addAll(Collection collection)   flatMap
     */
    @Test
    public void test7(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
        List list2 = new ArrayList<>();
        list2.add(11);
        list2.add(22);
        list2.add(list);
        list2.addAll(list);

        System.out.println(list2);
    }



    /**
     * 排序
     * sorted()--自然排序(Comparable)
     * sorted(Comparator com)--定制排序(Comparator)
     */
    @Test
    public void test8(){
        List<String> list = Arrays.asList("ccc","aaa","bbb","ddd","eee");
        list.stream()
                .sorted()
                .forEach(System.out::println);

        System.out.println("-----------------------------------------------");

        employees.stream()
                .sorted((e1,e2)->{
                    if(e1.getAge() == e2.getAge()){
                        return e1.getName().compareTo(e2.getName());
                    }else {
                        return -Integer.compare(e1.getAge(),e2.getAge());
                    }
                }).forEach(System.out::println);
    }



}
